package com.wave.gate.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;

import com.wave.gate.enums.AudioEnum;


import javazoom.jl.player.Player;
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;

import static com.wave.gate.util.GuavaCache.AI_WS_CACHE;

/**
 * Java 播放音频
 *
 * @ClassName: MusicPlayer
 * @Description: TODO
 * @author: tanlei
 * @date: 2019年10月25日 下午12:28:41
 * @Copyright: hyacinth
 */
@Slf4j
@Component
public class VoicePlayerUtil {

    private static VoicePlayerUtil instance;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    private static String path;

    @Value("${mp3.file.path}")
    private String tempPath;
    ExecutorService executor = null;
    @PostConstruct
    public void init(){
        instance = this;
        instance.threadPoolTaskExecutor = this.threadPoolTaskExecutor;
        instance.executor = Executors.newSingleThreadExecutor();
        path = tempPath;
    }

    private static DataLine.Info info = null;
    private static AudioFormat format = null;
    private static SourceDataLine line = null;
    private static AudioInputStream audio = null;

    public static void main(String[] args) throws Exception {
        VoicePlayerUtil player = new VoicePlayerUtil();
        //player.audio_to_pcm("E:\\KuGou\\左宏元 - 功德圆满 (情与法笛子版).mp3", "E:\\KuGou\\左宏元 - 功德圆满 (情与法笛子版).pcm");

        //player.get_info("C:\\Users\\Administrator\\Desktop\\梦涵 - 加减乘除.wav");

        //player.play("C:\\Users\\Administrator\\Desktop\\梦涵 - 加减乘除.pcm");
        //player.play("C:\\Users\\Administrator\\Desktop\\梦涵 - 加减乘除.wav");
        //play("C:\\Users\\tanlei\\Downloads\\690831080.mp3");
        //player.play("C:\\Users\\Administrator\\Desktop\\梦涵 - 加减乘除.flac");
    }


    /**
     * 播放音频
     * @param type：语音播放类型
     *            1：人脸核验失败，禁止通行
     *            2：物品重量不正确，禁止通行
     *            3：手机二维码验证失败，禁止通行
     *            4：令牌二维码验证失败，禁止通行
     *            5：待检区内仅限站1人(此语音已改成：请尾随人员退出)
     *            6：违规跨越，禁止通行
     *            7：违规弯腰/下蹲，禁止通行
     *            8：违规携带金属物品，禁止通行
     *            9：人脸核验完成，继续核验中(此语音已改成：核验中)
     *            10：核验通过，请通行
     *            11：AB门存在多人，禁止通行(此语音已改成：发现尾随，请人员全部退出)
     *            12:请退出通道
     *            13:请勿在通道内滞留
     *            14:违规抛物，禁止通行
     *            15:未穿供应商马甲，禁止通行
     *            16:超时未进入
     *            17:一路顺风
     */
    public static int count = 0;
    public static void voicePlay(int type) throws InterruptedException {
        instance.executor.execute(()->{
            InputStream inputStream = null;
            File tempFile = null;
            try {
//                File file = new File(path);
//                if (!file.exists() && !file .isDirectory()){
//                    file.mkdirs();
//                }
//                inputStream = new ClassPathResource("static/" + type + ".mp3").getInputStream();
//                tempFile = File.createTempFile(  type + "_temp", ".mp3", file);
//                FileUtils.copyInputStreamToFile(inputStream, tempFile);
//                play(tempFile.getPath());

                //换成这种方式，但是这种方式只能支持mp3
                //inputStream = new ClassPathResource("static/" + type + ".mp3").getInputStream();

                inputStream = new FileInputStream(path + type + ".mp3");
                Player player = new Player(inputStream);

                //log.info("AI_WS_CACHE.getIfPresent(ws)!=null===:{}",AI_WS_CACHE.getIfPresent("ws")!=null);
                //log.info("type == 18===:{}",type == 18);
                if(AI_WS_CACHE.getIfPresent("ws")!=null && type == 18){
                    //log.info("player.getPosition==========:{}",player.getPosition());
                    player.close();
                    //log.info("尾随语音停止次数count:{}", ++count);
                    return;
                }

                player.play();

            } catch (Exception e) {
                e.printStackTrace();
                log.error("播放音频（{}）异常", type + ".mp3");
            }finally {
                //tempFile.delete();
                IOUtils.closeQuietly(inputStream);
            }
        });

    }

    /**
     * Java Music 播放
     *
     * @param path 文件路径
     * @throws Exception
     * @Title: play_pcm
     * @Description: 播放 pcm
     * @date 2019年10月25日 下午12:28:41
     */
    public static void play(String path) throws Exception {
        load(path);
        try {
            line = (SourceDataLine) AudioSystem.getLine(info);
            line.open(format);
            line.start();
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = audio.read(buffer)) > 0) {
                line.write(buffer, 0, len);
            }
            line.drain();
            line.stop();
            line.close();
            audio.close();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 加载音频
     *
     * @param url
     * @throws Exception
     * @date 2022年1月7日14点15分
     */
    public void load(URL url) throws Exception {
        load(AudioSystem.getAudioInputStream(url));
    }

    /**
     * 加载音频
     *
     * @param file
     * @throws Exception
     * @date 2022年1月7日14点15分
     */
    public static void load(File file) throws Exception {
        String name = file.getName();
        if (AudioEnum.isSupport(name)) {
            if (AudioEnum.getIndex(name) == AudioEnum.MP3.index()) {
                MpegAudioFileReader reader = new MpegAudioFileReader();
                load(reader.getAudioInputStream(file));
            } else {
                load(AudioSystem.getAudioInputStream(file));
            }
        }
    }

    /**
     * 加载音频
     *
     * @param path
     * @throws Exception
     * @date 2022年1月7日14点15分
     */
    public static void load(String path) throws Exception {
        load(new File(path));
    }

    /**
     * 加载音频
     *
     * @param stream
     * @throws Exception
     * @date 2022年1月7日14点15分
     */
    public static void load(InputStream stream) throws Exception {
        load_audio(AudioSystem.getAudioInputStream(stream));
    }

    /**
     * 加载音频
     *
     * @param encoding
     * @param stream
     * @date 2022年1月7日14点15分
     */
    public void load(AudioFormat.Encoding encoding, AudioInputStream stream) {
        load_audio(AudioSystem.getAudioInputStream(encoding, stream));
    }

    /**
     * 加载音频
     *
     * @param format
     * @param stream
     * @date 2022年1月7日14点15分
     */
    public void load(AudioFormat format, AudioInputStream stream) {
        load_audio(AudioSystem.getAudioInputStream(format, stream));
    }

    /**
     * 加载音频
     *
     * @param stream 音频流
     * @date 2022年1月7日14点15分
     */
    public static void load_audio(AudioInputStream stream) {
        try {
            format = stream.getFormat();
            format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, format.getSampleRate(), 16, format.getChannels(),
                    format.getChannels() * 2, format.getSampleRate(), false);
            audio = AudioSystem.getAudioInputStream(format, stream);
            info = new DataLine.Info(SourceDataLine.class, format, AudioSystem.NOT_SPECIFIED);
            line = (SourceDataLine) AudioSystem.getLine(info);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 导出文件为PCM
     *
     * @param src 音频文件路径
     * @param dst PCM文件导出路径
     * @throws Exception
     * @date 2022年1月7日14点15分
     */
    private void audio_to_pcm(String src, String dst) throws Exception {
        load(src);
        AudioSystem.write(audio, AudioFileFormat.Type.WAVE, new File(dst));
        line.close();
        audio.close();
    }

    /**
     * Java Music 获取wav或者pcm文件的编码信息
     *
     * @param path wav或者pcm文件路径
     * @return wav或者pcm文件的编码信息
     * @Title: get_info
     * @Description: 获取wav或者pcm文件的编码信息
     * @date 2019年10月25日 下午12:28:41
     */
    public String get_info(String path) {
        File file = new File(path);
        AudioInputStream ais;
        String result = "";
        try {
            ais = AudioSystem.getAudioInputStream(file);
            AudioFormat af = ais.getFormat();
            result = af.toString();
            System.out.println(result);
            System.out.println("音频总帧数：" + ais.getFrameLength());
            System.out.println("每秒播放帧数：" + af.getSampleRate());
            float len = ais.getFrameLength() / af.getSampleRate();
            System.out.println("音频时长（秒）：" + len);
            System.out.println("音频时长：" + (int) len / 60 + "分" + len % 60 + "秒");
        } catch (UnsupportedAudioFileException e) {
            throw new RuntimeException(e.getMessage());
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage());
        }
        return result;
    }
}
